﻿using AJWPFAdmin.Core.Mvvm;
using Prism.Services.Dialogs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media.Imaging;
using System.Windows.Media;
using System.Windows.Input;
using Prism.Commands;

namespace AJWPFAdmin.Core.Components.AJFilePicker.ViewModels
{
    public class ImagePreviewerViewModel : ViewModelBase, IDialogAware
    {
        private string _dialogTitle;
        public string DialogTitle
        {
            get { return _dialogTitle; }
            set { SetProperty(ref _dialogTitle, value); }
        }

        private double _height;
        public double Height
        {
            get { return _height; }
            set { SetProperty(ref _height, value); }
        }

        private double _width;
        public double Width
        {
            get { return _width; }
            set { SetProperty(ref _width, value); }
        }

        private BitmapImage _image;
        public BitmapImage Image
        {
            get { return _image; }
            set { SetProperty(ref _image, value); }
        }

        private System.Windows.Controls.Border _border;

        private DelegateCommand<System.Windows.Controls.Border> _borderLoadedCmd;
        public DelegateCommand<System.Windows.Controls.Border> BorderLoadedCmd =>
            _borderLoadedCmd ?? (_borderLoadedCmd = new DelegateCommand<System.Windows.Controls.Border>(ExecuteBorderLoadedCmd));

        void ExecuteBorderLoadedCmd(System.Windows.Controls.Border parameter)
        {
            _border = parameter;
        }


        private System.Windows.Controls.Image _imageCtrl;
        private Point _start;
        private Point _origin;

        private DelegateCommand<System.Windows.Controls.Image> _imageLoadedCmd;
        public DelegateCommand<System.Windows.Controls.Image> ImageLoadedCmd =>
            _imageLoadedCmd ?? (_imageLoadedCmd = new DelegateCommand<System.Windows.Controls.Image>(ExecuteImageLoadedCmd));

        void ExecuteImageLoadedCmd(System.Windows.Controls.Image parameter)
        {
            _imageCtrl = parameter;
        }

        private DelegateCommand<MouseButtonEventArgs> _mouseDownCmd;
        public DelegateCommand<MouseButtonEventArgs> MouseDownCmd =>
            _mouseDownCmd ?? (_mouseDownCmd = new DelegateCommand<MouseButtonEventArgs>(ExecuteMouseDownCmd));

        void ExecuteMouseDownCmd(MouseButtonEventArgs e)
        {
            if (_imageCtrl.IsMouseCaptured)
            {
                return;
            }
            _imageCtrl.CaptureMouse();

            _start = e.GetPosition(_border);
            _origin.X = _imageCtrl.RenderTransform.Value.OffsetX;
            _origin.Y = _imageCtrl.RenderTransform.Value.OffsetY;
            _imageCtrl.Cursor = Cursors.Hand;
        }

        private DelegateCommand<MouseButtonEventArgs> _mouseUpCmd;
        public DelegateCommand<MouseButtonEventArgs> MouseUpCmd =>
            _mouseUpCmd ?? (_mouseUpCmd = new DelegateCommand<MouseButtonEventArgs>(ExecuteMouseUpCmd));

        void ExecuteMouseUpCmd(MouseButtonEventArgs parameter)
        {
            _imageCtrl.ReleaseMouseCapture();
            _imageCtrl.Cursor = null;
        }

        private DelegateCommand<MouseEventArgs> _mouseMoveCmd;
        public DelegateCommand<MouseEventArgs> MouseMoveCmd =>
            _mouseMoveCmd ?? (_mouseMoveCmd = new DelegateCommand<MouseEventArgs>(ExecuteMouseMoveCmd));

        void ExecuteMouseMoveCmd(MouseEventArgs e)
        {
            if (!_imageCtrl.IsMouseCaptured)
            {
                return;
            }

            var p = e.MouseDevice.GetPosition(_border);

            var m = _imageCtrl.RenderTransform.Value;

            m.OffsetX = _origin.X + (p.X - _start.X);
            m.OffsetY = _origin.Y + (p.Y - _start.Y);

            _imageCtrl.RenderTransform = new MatrixTransform(m);
        }

        private DelegateCommand<MouseWheelEventArgs> _mouseWheelCmd;
        public DelegateCommand<MouseWheelEventArgs> MouseWheelCmd =>
            _mouseWheelCmd ?? (_mouseWheelCmd = new DelegateCommand<MouseWheelEventArgs>(ExecuteMouseWheelCmd));

        void ExecuteMouseWheelCmd(MouseWheelEventArgs e)
        {
            var p = e.MouseDevice.GetPosition(_imageCtrl);

            var m = _imageCtrl.RenderTransform.Value;

            if (e.Delta > 0)
            {
                m.ScaleAtPrepend(1.1, 1.1, p.X, p.Y);
            }
            else
            {
                m.ScaleAtPrepend(1 / 1.1, 1 / 1.1, p.X, p.Y);
            }
            _imageCtrl.RenderTransform = new MatrixTransform(m);
        }

        public ImagePreviewerViewModel()
        {
            Width = SystemParameters.WorkArea.Size.Width * 0.8;
            Height = SystemParameters.WorkArea.Size.Height * 0.8;
        }

        public string Title => string.Empty;

        public event Action<IDialogResult> RequestClose;

        public bool CanCloseDialog()
        {
            return true;
        }

        public void OnDialogClosed()
        {
            //throw new NotImplementedException();
        }

        public void OnDialogOpened(IDialogParameters parameters)
        {
            parameters.TryGetValue<BitmapImage>("data", out var data);
            parameters.TryGetValue<string>("name", out var name);
            Image = data;
            DialogTitle = name;
        }
    }
}
